<script setup lang="ts">
import {
  computed,
  ref,
  watch,
  inject,
  onActivated,
  onDeactivated,
  onMounted,
  onBeforeUnmount,
} from "vue";
import { Line, Circle, Canvas } from "fabric";
import _ from "lodash";
import { sendSocketIoMsg } from "@renderer/api/request";
import { EnumOpType, EnumViewType } from "@renderer/assets/types";
import { useSystemSettingStore } from "@renderer/store/pinia/systemSetting";
import { useImageDataStore } from "@renderer/store/pinia/imageData";

const { activeOpType } = inject("viewerInfo") as any;
const initFlag = ref(false);
const props = defineProps({
  viewType: {
    type: String,
    default: "",
  },
  viewId: {
    type: String,
    default: "",
  },
});
const containerRef = ref<any>(null);
const canvasRef = ref<any>(null);
const radius = 5;
const isDraggingRef = ref(false);
const imgStore = useImageDataStore()

const currentViewMprCenter = computed(() => {
  if (imgStore.mprCenterObj[props.viewId]) {
    return  imgStore.mprCenterObj[props.viewId]
  }else {
    return {
      position: [0, 0],
      mip: {
        delta_x: 0,
        delta_y: 0
      }
    }
  }
})

const centerPointRef = computed(() => {
  return {
    x:currentViewMprCenter.value.position[0],
    y: currentViewMprCenter.value.position[1],
  };
});

const containerAspectRef = ref({
  width: 0,
  height: 0,
})

const mipRef = computed(() => {
  return {
    delta_x: currentViewMprCenter.value.mip.delta_x,
    delta_y: currentViewMprCenter.value.mip.delta_y,
  };
});
onMounted(() => {
  console.log("cross-layer mounted");
  watchResize();
});
onActivated(() => {
  console.log("cross-layer activated");
  watchResize();
});
onDeactivated(() => {
  console.log("cross-layer deactivated");
  stopWatchResize();
});

onBeforeUnmount(() => {
  console.log("cross-layer onBeforeUnmount");
  stopWatchResize();
});

const stopWatchResize = () => {
  if (resizeObserver) {
    resizeObserver.disconnect();
    resizeObserver = null;
  }
};

const systemSettingStore = useSystemSettingStore();

const getColor = () => {
  if (props.viewType === EnumViewType.ax) {
    return {
      hColor: systemSettingStore.crossColor[EnumViewType.ax].trim(),
      vColor: systemSettingStore.crossColor[EnumViewType.cor].trim(),
    };
  } else if (props.viewType === EnumViewType.sag) {
    return {
      hColor: systemSettingStore.crossColor[EnumViewType.sag].trim(),
      vColor: systemSettingStore.crossColor[EnumViewType.ax].trim(),
    };
  } else {
    return {
      hColor: systemSettingStore.crossColor[EnumViewType.sag].trim(),
      vColor: systemSettingStore.crossColor[EnumViewType.cor].trim(),
    };
  }
};
const getLineWidth = () => {
  return systemSettingStore.crossLineWidth;
};

let canvas: Canvas;
let horizontalLine1: Line;
let horizontalLine2: Line;
let verticalLine1: Line;
let verticalLine2: Line;
let circle: Circle;

let upMipHorizontalLine: Line;
let downMipHorizontalLine: Line;
let leftMipVerticalLine: Line;
let rightMipVerticalLine: Line;

const initLines = () => {
  const { x, y } = centerPointRef.value;
  const lineStrokeWidth = getLineWidth();
  const { hColor, vColor } = getColor();
  // 初始化线段
  horizontalLine1 = new Line([0, y, x - radius, y], {
    stroke: hColor,
    strokeWidth: lineStrokeWidth,
    selectable: false,
    hoverCursor: "default",
  });
  horizontalLine2 = new Line([x + radius, y, canvas.width, y], {
    stroke: hColor,
    strokeWidth: lineStrokeWidth,
    selectable: false,
    hoverCursor: "default",
  });

  verticalLine1 = new Line([x, 0, x, y - radius], {
    stroke: vColor,
    strokeWidth: lineStrokeWidth,
    selectable: false,
    hoverCursor: "default",
  });

  verticalLine2 = new Line([x, y + radius, x, canvas.height], {
    stroke: vColor,
    strokeWidth: lineStrokeWidth,
    selectable: false,
    hoverCursor: "default",
  });

  canvas.add(horizontalLine1, horizontalLine2, verticalLine1, verticalLine2);
};
const initMipLines = () => {
  const { x, y } = centerPointRef.value;
  const deltaX = mipRef.value.delta_x;
  const deltaY = mipRef.value.delta_y;
  const w = canvas.width as number;
  const h = canvas.height as number;
  const lineStrokeWidth = getLineWidth();
  const { hColor, vColor } = getColor();
  leftMipVerticalLine = new Line([x - deltaX, 0, x - deltaX, h], {
    stroke: vColor,
    strokeWidth: lineStrokeWidth,
    selectable: false,
    hoverCursor: "default",
    strokeDashArray: [3, 3],
  });
  rightMipVerticalLine = new Line([x + deltaX, 0, x + deltaX, h], {
    stroke: vColor,
    strokeWidth: lineStrokeWidth,
    selectable: false,
    hoverCursor: "default",
    strokeDashArray: [3, 3],
  });
  canvas.add(leftMipVerticalLine, rightMipVerticalLine);

  upMipHorizontalLine = new Line([0, y - deltaY, w, y - deltaY], {
    stroke: hColor,
    strokeWidth: lineStrokeWidth,
    selectable: false,
    hoverCursor: "default",
    strokeDashArray: [3, 3],
  });
  downMipHorizontalLine = new Line([0, y + deltaY, w, y + deltaY], {
    stroke: hColor,
    strokeWidth: lineStrokeWidth,
    selectable: false,
    hoverCursor: "default",
    strokeDashArray: [3, 3],
  });
  canvas.add(upMipHorizontalLine, downMipHorizontalLine);
};

const initCircle = () => {
  const { x, y } = centerPointRef.value;
  const lineStrokeWidth = getLineWidth();
  circle = new Circle({
    left: x - radius,
    top: y - radius,
    radius: radius,
    stroke: "",
    strokeWidth: lineStrokeWidth,
    hasControls: false,
    hasBorders: false,
    fill: "rgba(255, 255, 255, 1)",
    hoverCursor: "default",
  });
  canvas.add(circle);
};


const render = () => {
  if (
    mipRef.value.delta_x === 0 &&
    leftMipVerticalLine !== null &&
    rightMipVerticalLine !== null
  ) {
    leftMipVerticalLine.set("visible", false);
    rightMipVerticalLine.set("visible", false);
  } else if (leftMipVerticalLine !== null && rightMipVerticalLine !== null) {
    leftMipVerticalLine.set("visible", true);
    rightMipVerticalLine.set("visible", true);
  }
  if (
    mipRef.value.delta_y === 0 &&
    upMipHorizontalLine !== null &&
    downMipHorizontalLine !== null
  ) {
    upMipHorizontalLine.set("visible", false);
    downMipHorizontalLine.set("visible", false);
  } else if (leftMipVerticalLine !== null && downMipHorizontalLine !== null) {
    upMipHorizontalLine.set("visible", true);
    downMipHorizontalLine.set("visible", true);
  }

  canvas.renderAll();
};

const updateLines = (
  x ,
  y ,
) => {
  if (!containerRef.value){
    console.log(`update line, not get size`)
    return;
  }
  // 更新线的位置而不是重新创建
  horizontalLine1?.set({
    x1: 0,
    y1: y,
    x2: x - radius,
    y2: y,
  });

  horizontalLine2?.set({
    x1: x + radius,
    y1: y,
    x2: canvasRef.value.width,
    y2: y,
  });

  verticalLine1?.set({
    x1: x,
    y1: 0,
    x2: x,
    y2: y - radius,
  });

  verticalLine2?.set({
    x1: x,
    y1: y + radius,
    x2: x,
    y2: canvasRef.value.height,
  });

  [horizontalLine1, horizontalLine2, verticalLine1, verticalLine2].forEach((line) => {
    line.setCoords();
  })
};

const updateMipLines = (
  x = centerPointRef.value.x,
  y = centerPointRef.value.y,
) => {
  const deltaX = mipRef.value.delta_x;
  const deltaY = mipRef.value.delta_y;
  const w = containerAspectRef.value.width as number;
  const h = containerAspectRef.value.height as number;
  leftMipVerticalLine.set({
    x1: x - deltaX,
    y1: 0,
    x2: x - deltaX,
    y2: h,
  });
  rightMipVerticalLine.set({
    x1: x + deltaX,
    y1: 0,
    x2: x + deltaX,
    y2: h,
  });
  upMipHorizontalLine.set({
    x1: 0,
    y1: y - deltaY,
    x2: w,
    y2: y - deltaY,
  });
  downMipHorizontalLine.set({
    x1: 0,
    y1: y + deltaY,
    x2: w,
    y2: y + deltaY,
  });
};

const updateCircles = () => {
  const { x, y } = centerPointRef.value;
  circle.set({
    left: x - radius,
    top: y - radius,
  });
  // 更新小球的坐标，以便其可以继续移动。
  circle.setCoords();
};

const updateCanvas = () => {
  if (containerRef.value === null) {
    return;
  }
  const { width, height } = containerRef.value.getBoundingClientRect();
  containerAspectRef.value = {
    width,
    height,
  }
  canvas.setDimensions({
    width: width,
    height: height,
  })
}


const startRender = () => {
  if (containerRef.value === null) {
    return;
  }

  const { width, height } = containerRef.value.getBoundingClientRect();
  if (width === 0 && height === 0) {
    console.error("crossLayer size 0");
    return;
  }
  console.log(`start render cross`);

  if (!initFlag.value){
    canvasRef.value.width = width;
    canvasRef.value.height = height;
    canvas = new Canvas(canvasRef.value, {});
    canvas.selection = false;
    watch(centerPointRef, _.debounce((newVal) => {
      if (!isDraggingRef.value) {
        updateCanvas()
        updateCircles();
        updateLines(newVal.x, newVal.y);
        render();
      }
    }));
    watch(mipRef, () => {
      // 如果, mip投影的delta_x /y 都为0 或者 用户正在拖动当前的视图。则不更新。
      if (
        (mipRef.value.delta_x === 0 && mipRef.value.delta_y === 0) ||
        isDraggingRef.value
      ) {
        return;
      }
      updateMipLines();
      render();
    },{
      deep: true,
    });
    initLines();
    initMipLines();
    initCircle();
    render();
    canvas.on("object:moving", _.throttle(function (e) {
      isDraggingRef.value = true;
      const { left, top } = e.target;
      if (isDraggingRef.value) {
        updateLines(left + radius, top + radius);
        updateMipLines(left + radius, top + radius);
      }
      const msg = {
        viewType: props.viewType,
        opType: "move_scroll_absolute",
        x: left + radius,
        y: top + radius,
      };
      sendSocketIoMsg(msg);
    }, 30),);

    canvas.on("mouse:up", () => {
      console.log("up clear drag status");
      isDraggingRef.value = false;
    });
    initFlag.value = true
  }else {
    console.log('resize set canvas aspect')
  }
};

let resizeObserver: ResizeObserver | null = null;

const watchResize = () => {
  if (!resizeObserver) {
    resizeObserver = new ResizeObserver(
      _.debounce((entries) => {
        console.log(`cross layer size change detected`);
        const { width, height } = entries[0].contentRect;
        if (width !== 0 && height !== 0) {
          startRender();
        }
      }, 0),
    );
  }
  resizeObserver.observe(containerRef.value);
};

const showHideLayer = computed(() => {
 return  activeOpType.value !== EnumOpType.cross
})
</script>

<template>
  <div ref="containerRef" class="w-full h-full">
    <canvas ref="canvasRef" class="w-full h-full"></canvas>
  </div>
  <canvas
    class="w-full h-full z-[10] absolute left-0 top-0"
    v-if="showHideLayer"
  ></canvas>
</template>
